package com.apes.fa.service;

import com.alibaba.fastjson.JSONObject;
import com.apes.fa.model.FaCard;
import com.apes.fa.model.FaCardAccount;
import com.apes.fa.model.FaExtractAssetDepreciation;
import com.apes.fa.report.FaAssetDepreciation;
import com.apes.fa.report.FaAssetDepreciationRepository;
import com.apes.fa.respository.FaCardAccountRepository;
import com.apes.fa.respository.FaCardRepository;
import com.apes.fa.respository.FaExtractAssetDepreciationRepository;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.outbox.OutboxEventService;
import com.apes.framework.plugin.outbox.OutboxPayloadWrapper;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.MapUtil;
import com.apes.scm.masterdata.frame.model.DutyCenter;
import com.apes.scm.masterdata.frame.repository.DutyCenterRepository;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.product.model.FaCategory;
import com.apes.scm.masterdata.product.repository.FaCategoryRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service("faExtractAssetDepreciationService")
public class FaExtractAssetDepreciationService extends DomainService {

    @Autowired
    private FaCardRepository faCardRepository;

    @Autowired
    private FaCardAccountRepository faCardAccountRepository;

    @Autowired
    private FaCardAccountService faCardAccountService;
    @Autowired
    private FaExtractAssetDepreciationRepository faExtractAssetDepreciationRepository;

    /**
     * 提取折旧
     */
    private FaExtractAssetDepreciation save(SimpleRequest request){
        String faType = "固定资产";
        JSONObject month = (JSONObject) request.get("MONTH");
        Calendar ca = Calendar.getInstance();
        ca.set(Calendar.MONTH,Integer.parseInt(month.getString("id")) -1);
        ca.set(Calendar.DAY_OF_MONTH, 1);
        Date firstDate = ca.getTime();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String format = sdf.format(firstDate);

        FaExtractAssetDepreciation faExtractAssetDepreciation = request.getO(FaExtractAssetDepreciation.class);
        String creator = faExtractAssetDepreciation.getOperator();
        PartyRole company = faExtractAssetDepreciation.getCompany();
        List<FaExtractAssetDepreciation> faExtractAssetDepreciations = faExtractAssetDepreciationRepository.findByTime(creator, company, new Date());
        if(faExtractAssetDepreciations.size() != 0 ){
            faExtractAssetDepreciations.forEach(i->{
                throw new RuntimeException("本月已折旧： "+i.getId());
            });

        }
        String companyId = faExtractAssetDepreciation.getCompany().getId();
        List<FaCard> faCards = faCardRepository.findCardByCompanyIdAndFaType(companyId,faType,format,1);
        for (FaCard faCard : faCards) {
            faCardAccountService.withdrawDepreciationCard(faCard,request);
        }
        faExtractAssetDepreciation = faExtractAssetDepreciationRepository.saveAndFlush(faExtractAssetDepreciation);

        /**资产报废或转移当月折旧**/
        String startDate = DateUtil.format(DateUtil.getMonthFirstDay(firstDate), DateUtil.SHOW_DATE_FORMAT) + " 00:00:00";
        String endDate = DateUtil.format(DateUtil.getMonthLastDay(firstDate), DateUtil.SHOW_DATE_FORMAT) + " 23:59:59";
        for (FaCardAccount faCardAccount : faCardAccountRepository.findAll(companyId, startDate, endDate)) {
            String faCarId = faCardAccount.getFaCardId();
            if (faCarId == null) continue;
            FaCard faCard = faCardRepository.findOne(faCarId);
            if (faCard != null && !faCards.contains(faCard)) {
                faCards.add(faCard);
            }
        }

        //资产分类折旧原值统计
        depreciationStatistics(faCards,format);

        //其它项统计
        String payload = JSONObject.toJSONString(MapUtil.mapper(
                "COMPANY_ID",companyId,
                "YEARMONTH",String.valueOf(Integer.parseInt(DateUtil.format(firstDate, "yyyyMM")))));
        publish(payload, faExtractAssetDepreciation.getId(), "event:faAsset.service.depreciation");


        return faExtractAssetDepreciation;

    }

    public void test(SimpleRequest request) {
        String format = request.get("enableDate");
        String companyId = request.get("companyId");
        List<FaCard> faCards = faCardRepository.findCardByCompanyIdAndFaType(companyId,"固定资产",format,1);

        /**资产报废或转移当月折旧**/
        Date firstDate = DateUtil.parse(format, DateUtil.SHOW_DATE_FORMAT);
        String startDate = DateUtil.format(DateUtil.getMonthFirstDay(firstDate), DateUtil.SHOW_DATE_FORMAT) + " 00:00:00";
        String endDate = DateUtil.format(DateUtil.getMonthLastDay(firstDate), DateUtil.SHOW_DATE_FORMAT) + " 23:59:59";
        for (FaCardAccount faCardAccount : faCardAccountRepository.findAll(companyId, startDate, endDate)) {
            String faCarId = faCardAccount.getFaCardId();
            if (faCarId == null) continue;
            FaCard faCard = faCardRepository.findOne(faCarId);
            if (faCard != null && !faCards.contains(faCard)) {
                faCards.add(faCard);
            }
        }

        //资产分类折旧原值统计
        depreciationStatistics(faCards,format);

        //其它项统计
        String payload = JSONObject.toJSONString(MapUtil.mapper(
                "COMPANY_ID",companyId,
                "YEARMONTH",String.valueOf(Integer.parseInt(DateUtil.format(DateUtil.parse(format, DateUtil.SHOW_DATE_FORMAT), "yyyyMM")))));
        publish(payload, "重新生成", "event:faAsset.service.depreciation");

    }

    /**
     * 资产分类折旧统计
     */
    public void depreciationStatistics(List<FaCard> faCards,String format){
        Map<String, List<FaCard>> collect = faCards.stream().collect(Collectors.groupingBy(v ->
                v.getCompany().getId()+";"+v.getDept().getCostCenterId().getId()+";"+v.getFaCategory().getId()));
        if (collect.isEmpty()) return;
        PartyRole role = faCards.get(0).getCompany();

        collect.forEach(
            (unique, items) -> {
                String[] uniques = unique.split(";");
                String company = uniques[0];  //公司
                String costCenter = uniques[1]; //成本中心
                String category = uniques[2];   //资产分类

                double originValue = items.stream().mapToDouble(FaCard::getOriginalValue).sum();
                double depreciationValue = items.stream().mapToDouble(FaCard::getDepreciation).sum();

                DutyCenter center = SpringManager.getBean(DutyCenterRepository.class).findOne(costCenter);
                FaCategory faCategory = SpringManager.getBean(FaCategoryRepository.class).findOne(category);

                FaAssetDepreciation depreciation = new FaAssetDepreciation();
                depreciation.setCompany(role);
                depreciation.setCostCenter(center);
                depreciation.setFaCategory(faCategory);
                depreciation.setMonthOriginalValue(originValue);
                depreciation.setMonthDepreciation(depreciationValue);
                depreciation.setFinanceDate(DateUtil.parse(format,DateUtil.SHOW_DATE_FORMAT));

                //创建
                depreciation.setState("create");

                SpringManager.getBean(FaAssetDepreciationRepository.class).saveAndFlush(depreciation);
            });
    }

    public void publish(String payload, String id, String subscriber) {
        OutboxPayloadWrapper wrapper = new OutboxPayloadWrapper();
        wrapper.setSubscriber(subscriber);
        wrapper.setPayload(payload);
        wrapper.setAggregateId(id);
        SpringManager.getBean(OutboxEventService.class).sendSaveEvent(wrapper);
    }

    private void findByDate(SimpleRequest request){
        Calendar ca = Calendar.getInstance();
        ca.setTime(new Date());
        ca.set(Calendar.DAY_OF_MONTH, 1);
        Date firstDate = ca.getTime();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String format = sdf.format(firstDate);
        String companyId = request.get("companyId").toString();
//        if(!faCardRepository.findCardByCompanyIdAndFaType(companyId, "固定资产", format, 1).isEmpty())
//            throw new RuntimeException("本月");
    }

}
